#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

#define TASK_NUM 10
typedef void(*task_t)();
task_t tasks[TASK_NUM];

void task1()
{
    printf("这是一个执行打印日志的任务, pid: %d\n", getpid());
}

void task2()
{
    printf("这是一个执行监测网络健康状态的任务, pid: %d\n", getpid());
}

void task3()
{
    printf("这是一个绘制图形界面的任务, pid: %d\n", getpid());
}

int AddTask(task_t t);

// 任务的管理代码
void InitTask()
{
    for (int i = 0; i < TASK_NUM; ++i)
        tasks[i] = NULL;
    AddTask(task1);
    AddTask(task2);
    AddTask(task3);
}

int AddTask(task_t t)
{
    int pos = 0;
    for (; pos < TASK_NUM; ++pos)
    {
        if (!tasks[pos])
        {
            tasks[pos] = t;
            return 0; // 添加成功
        }
    }
    return -1; // 添加失败
}

void DelTask(){}
void CheckTask(){}
void UpdateTask(){}

void ExecuteTask()
{
    for (int i = 0; i < TASK_NUM; ++i)
    {
        if (!tasks[i]) continue;
        tasks[i]();
    }
}

int main()
{
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork");
        return errno;
    }
    else if (id == 0)
    {
        // child
        int cnt = 1;
        while (cnt)
        {
            printf("child, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt);
            cnt--;
            sleep(1);
        }
        exit(1); // 为了测试明显， 我们改成1
    }
    else 
    {
        //parent
        int status = 0;
        InitTask();
        while (1) // 轮询
        {
            pid_t ret = waitpid(id, &status, WNOHANG); // 非阻塞
            if  (ret > 0) // 父进程拿到的id就是子进程的pid
            {
                if (WIFEXITED(status))
                {
                    printf("进程是正常跑完的，退出码：%d\n", WEXITSTATUS(status));
                }
                else 
                {
                    printf("进程出异常了\n"); // 走到这里父进程调用没问题，是子进程出异常了
                }
                break;
            }
            else if (ret < 0)
            {
                printf("wait failed!\n"); // 走到这里是父进程调用waitpid函数失败了
                break;
            }
            else 
            {
                ExecuteTask();
                usleep(500000);
            }
        }
    }
    return 0;
}


